HTMLWidgets.widget({
  name: 'peakD3',
  type: 'output',
  factory: function(el, width, height) {
    // 初始化容器结构


    const controls = d3.select(el)
      .append("div")
      .attr("class", "controls");

    controls.append("button")
      .attr("id", "zoom-in")
      .text("放大 X 轴");
    controls.append("button")
      .attr("id", "zoom-out")
      .text("缩小 X 轴");
    controls.append("button")
      .attr("id", "reset-zoom")
      .text("重置缩放");

      // 新增下载按钮
    const downloadButton = controls.append("button")
      .attr("id", "download-chart")
      .text("下载图表");

    // 下载下拉菜单
    const downloadMenu = controls.append("div")
      .attr("id", "download-menu")
      .attr("class", "download-menu")
      .style("display", "none")
      .style("position", "absolute")
      .style("background", "white")
      .style("border", "1px solid #e0e0e0")
      .style("border-radius", "4px")
      .style("box-shadow", "0 2px 8px rgba(0,0,0,0.1)")
      .style("padding", "8px 0")
      .style("z-index", "1000");

    // 下载选项
    const formats = [
      {id: "download-svg", text: "SVG格式", type: "svg"},
      {id: "download-png", text: "PNG格式", type: "png"}
    ];

    formats.forEach(format => {
      downloadMenu.append("div")
        .attr("id", format.id)
        .attr("class", "download-option")
        .style("padding", "8px 16px")
        .style("cursor", "pointer")
        .style("hover", "background: #f5f5f5")
        .text(format.text)
        .on("click", () => downloadChart(format.type));
    });

    // 下载菜单显示/隐藏逻辑
    downloadButton.on("click", (event) => {
      event.stopPropagation();
      const rect = downloadButton.node().getBoundingClientRect();
      const containerRect = el.getBoundingClientRect();

      downloadMenu.style("display", downloadMenu.style("display") === "block" ? "none" : "block")
        .style("left", `${rect.left - containerRect.left}px`)
        .style("top", `${rect.top - containerRect.top + rect.height + 5}px`);
    });

    // 点击其他区域关闭下载菜单
    d3.select(document).on("click", () => {
      downloadMenu.style("display", "none");
    });

            // 下载图表函数
    function downloadChart(format) {
      // 隐藏下载菜单
      downloadMenu.style("display", "none");

      const now = new Date();
      const timestamp = `${now.getFullYear()}${(now.getMonth()+1).toString().padStart(2,'0')}${now.getDate().toString().padStart(2,'0')}_${now.getHours().toString().padStart(2,'0')}${now.getMinutes().toString().padStart(2,'0')}`;
      const filename = `mass_spectrum_${timestamp}`;

      switch(format) {
        case "svg":
          downloadSVG(filename);
          break;
        case "png":
          downloadPNG(filename);
          break;
        case "pdf":
          downloadPDF(filename);
          break;
        case "html":
          downloadHTML(filename);
          break;
      }
    }

    // 下载SVG格式
    function downloadSVG(filename) {
      // 克隆SVG以避免影响原始图表
      const svgClone = svg.node().cloneNode(true);

      // 移除裁剪以确保完整显示
      d3.select(svgClone).selectAll("[clip-path]").attr("clip-path", "none");

      // 序列化SVG
      const serializer = new XMLSerializer();
      let source = serializer.serializeToString(svgClone);

      // 添加XML声明
      source = '<?xml version="1.0" standalone="no"?>\r\n' + source;

      // 创建Blob并下载
      const url = URL.createObjectURL(new Blob([source], {type: "image/svg+xml"}));
      const link = document.createElement("a");
      link.href = url;
      link.download = `${filename}.svg`;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      URL.revokeObjectURL(url);
    }

    // 下载PNG格式
    function downloadPNG(filename) {
      // 获取SVG数据
      const svgNode = svg.node();
      const serializer = new XMLSerializer();
      let source = serializer.serializeToString(svgNode);

      // 添加XML声明
      source = '<?xml version="1.0" standalone="no"?>\r\n' + source;

      // 创建临时SVG Blob
      const image = new Image();
      const svgBlob = new Blob([source], {type: "image/svg+xml;charset=utf-8"});
      const url = URL.createObjectURL(svgBlob);

      image.onload = function() {
        // 创建Canvas
        const canvas = document.createElement("canvas");
        canvas.width = parseInt(svg.attr("width"));
        canvas.height = parseInt(svg.attr("height"));
        const ctx = canvas.getContext("2d");

        // 绘制到Canvas
        ctx.fillStyle = "#ffffff";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(image, 0, 0);

        // 下载
        const link = document.createElement("a");
        link.download = `${filename}.png`;
        link.href = canvas.toDataURL("image/png");
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        URL.revokeObjectURL(url);
      };

      image.src = url;
    }





  //////////////////////////////////////////////

    const chartContainer = d3.select(el)
      .append("div")
      .attr("class", "chart-container")
      .style("position", "relative");


    //const svgContainer = chartContainer.append("div")
      //.attr("class", "ggplot-container");
      //svgContainer.html(");



    chartContainer.append("div")
      .attr("id", "tooltip")
      .attr("class", "tooltip");



    const svg = chartContainer.append("svg");

    // 注入明亮主题CSS
    const style = document.createElement("style");
    style.textContent = `
     // .chart-container {
      //  background: #ffffff;
      //  border-radius: 8px;
      //  padding: 20px;
      //  margin: 10px 0;
     //   box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
     // }
      .controls {
        display: flex;
        gap: 10px;
        margin: 10px 0;
      }
      button {
        background: #4285f4;
        color: white;
        border: none;
        padding: 8px 16px;
        border-radius: 4px;
        cursor: pointer;
        font-size: 0.9rem;
        transition: background 0.2s;
      }
      button:hover {
        background: #3367d6;
      }
      .tooltip {
        position: absolute;
        background: white;
        border: 1px solid #e0e0e0;
        border-radius: 6px;
        padding: 10px;
        box-shadow: 0 3px 15px rgba(0, 0, 0, 0.1);
        font-size: 0.9rem;
        pointer-events: none;
        opacity: 0;
        transition: opacity 0.2s;
        z-index: 100;
        min-width: 200px;
        color: #333;
      }
      .tooltip-title {
        font-weight: bold;
        color: #4285f4;
        margin-bottom: 5px;
        padding-bottom: 5px;
        border-bottom: 1px solid #f0f0f0;
      }
      .tooltip-row {
        margin: 3px 0;
        display: flex;
        justify-content: space-between;
      }
      .tooltip-label {
        color: #666;
      }
      .spectrum-bar {
        stroke-width: 2;
      }
      .spectrum-bar:hover {
        stroke-width: 4;
        stroke-opacity: 0.9;
      }
      .ion-label {
        font-size: 12px;
        font-weight: bold;
      }
      .axis text {
        fill: #555;
        font-size: 11px;
      }
      .axis path, .axis line {
        stroke: #ddd;
      }
      //.ggplot-container {
 // margin-top: 0px;
  //width: 100%;
 // height: auto;
 // text-align: center;

//}
    `;
    document.head.appendChild(style);

    return {
      renderValue: function(x) {

                // 从R接收的参数，控制按钮是否显示
        const showControls = x.showControls !== undefined ? x.showControls : true;

        // 根据参数显示或隐藏控制区域
        controls.style("display", showControls ? "" : "none");

        //svgContainer.html(x.ggplotSvg);
        //svgContainer.html("asasasas");
        //svgContainer.html("<div class='ggplot-title'>质谱图</div");



        //const massSpectrumData = [
         // { mz: 129, intensity: 640971, ion_type: "?", label: "" },
         // { mz: 129, intensity: 10306, ion_type: "?", label: "" },
         // { mz: 129, intensity: 10431, ion_type: "?", label: "" },
         // { mz: 129, intensity: 212045, ion_type: "IKD", label: "IKD" },
         // { mz: 130, intensity: 6847, ion_type: "?", label: "" },
         // { mz: 130, intensity: 46185, ion_type: "y", label: "y1-NH3" },
         // { mz: 130, intensity: 11993, ion_type: "IKD", label: "IKD+i" },
         // { mz: 143, intensity: 7598, ion_type: "?", label: "" },
         // { mz: 143, intensity: 7247, ion_type: "?", label: "" },
        //  { mz: 143, intensity: 112950, ion_type: "?", label: "" }
       // ];

        const massSpectrumData = HTMLWidgets.dataframeToD3(x.data);

        const formattedData = massSpectrumData.map(d => {
          let type = "other";
          if (d.ion_type === "b") type = "b";
          if (d.ion_type === "y") type = "y";
          return {
            mz: d.mz,
            intensity: d.intensity,
            type: type,
            ionType: d.ion_type,
            label: d.label || (d.ion_type !== "?" ? d.ion_type : "")
          };
        });

        // 尺寸设置
        const margin = { top: 70, right: 40, bottom: 60, left: 80 };
        // const containerWidth = el.clientWidth;
         const containerWidth = width;
        const containerHeight = height;
        const innerWidth = containerWidth - margin.left - margin.right;
        const innerHeight = containerHeight - margin.top - margin.bottom;

        // 设置SVG尺寸
        svg.attr("width", containerWidth)
           .attr("height", containerHeight);

        // ########## 核心修改：将你的 SVG 嵌入到主 SVG 中 ##########
        if (x.ggplotSvg) {
          // 1. 解析 SVG 字符串
          const tempDiv = document.createElement("div");
          tempDiv.innerHTML = x.ggplotSvg; // 解析 R 传递的 SVG 内容
          const importedSvg = tempDiv.querySelector("svg"); // 获取 SVG 根元素

          if (importedSvg) {
            // 2. 在主 SVG 中创建一个分组，用于放置你的 SVG
            const importedGroup = svg.append("g")
              .attr("class", "imported-svg-group")
              // 定位：放在主 SVG 顶部居中（可根据需求调整）
              .attr("transform", `translate(${margin.left + innerWidth/2}, ${margin.top - 20})`);

            // 3. 提取并复制 SVG 内部元素到分组中（避免重复 SVG 根标签）
            Array.from(importedSvg.children).forEach(child => {
              importedGroup.node().appendChild(child.cloneNode(true));
            });

            // 4. 调整尺寸和位置（关键：适配主 SVG 布局）
            // 获取导入 SVG 的原始尺寸（从 viewBox 或 width/height 提取）
            const viewBox = importedSvg.getAttribute("viewBox") || `0 0 ${importedSvg.width} ${importedSvg.height}`;
            const [xVb, yVb, widthVb, heightVb] = viewBox.split(" ").map(Number);

            // 缩放比例（根据需要调整，这里缩小到 40%）
            const scale = 1;

            // 重新定位（使导入的 SVG 自身居中）
            importedGroup.attr("transform", `
              translate(${margin.left + innerWidth/2}, ${margin.top - 25})
              scale(${scale})
              translate(${-widthVb/2}, ${-heightVb/2})
            `);
          }
        }

        // 创建裁剪区域（解决内容超出问题）
        svg.append("defs").append("clipPath")
          .attr("id", "chart-clip")
          .append("rect")
          .attr("x", 0)
          .attr("y", 0)
          .attr("width", innerWidth)
          .attr("height", innerHeight);

        // 创建主绘图组并应用裁剪
        const mainGroup = svg.append("g")
          .attr("transform", `translate(${margin.left},${margin.top})`)
          .attr("clip-path", "url(#chart-clip)");

        // 比例尺
        const xScale = d3.scaleLinear()
          .domain([d3.min(formattedData, d => d.mz) - 20, d3.max(formattedData, d => d.mz) + 20])
          .range([0, innerWidth]);

        const maxIntensity = d3.max(formattedData, d => d.intensity);
        const yScale = d3.scaleLinear()
          .domain([0, maxIntensity])
          .range([innerHeight, 0]);

        // 缩放行为
        const zoom = d3.zoom()
          .scaleExtent([1, x.zoomRatio])
          .translateExtent([[0, 0], [innerWidth, innerHeight]])
          .extent([[0, 0], [innerWidth, innerHeight]])
          .on("zoom", zoomed);

        // 缩放区域
        mainGroup.append("rect")
          .attr("width", innerWidth)
          .attr("height", innerHeight)
          .attr("fill", "none")
          .attr("pointer-events", "all")
          .call(zoom);

        // 坐标轴
        const xAxisGroup = svg.append("g")
          .attr("class", "axis x-axis")
          .attr("transform", `translate(${margin.left},${margin.top + innerHeight})`);

        const yAxisGroup = svg.append("g")
          .attr("class", "axis y-axis")
          .attr("transform", `translate(${margin.left},${margin.top})`);

        xAxisGroup.call(d3.axisBottom(xScale));

        if (x.axisY=="absolute") {
          yAxisGroup.call(d3.axisLeft(yScale));

        }else if(x.axisY == "relative"){
          yAxisGroup.call(d3.axisLeft(yScale).tickFormat(d => (d / maxIntensity * 100).toFixed(0) + "%"));
        }else{

        }




        // 绘制谱峰
        function drawSpectrum() {
          mainGroup.selectAll(".spectrum-bar").remove();
          mainGroup.selectAll(".ion-label").remove();

          // 谱峰
          mainGroup.selectAll(".spectrum-bar")
            .data(formattedData)
            .enter()
            .append("line")
            .attr("class", "spectrum-bar")
            .attr("x1", d => xScale(d.mz))
            .attr("x2", d => xScale(d.mz))
            .attr("y1", yScale(0))
            .attr("y2", d => yScale(d.intensity))
            .attr("stroke", d => {
              if (d.type === 'b') return x.bColor; // 谷歌蓝
              if (d.type === 'y') return x.yColor; // 谷歌红
              return x.otherColor; // 紫色
            })
            .on("mouseover", handleMouseOver)
            .on("mousemove", handleMouseMove)
            .on("mouseout", handleMouseOut);

          // 标签
          if(x.ifLabel){
                      mainGroup.selectAll(".ion-label")
            .data(formattedData.filter(d => d.label !== ""))
            .enter()
            .append("text")
            .attr("class", "ion-label")
            .attr("x", d => xScale(d.mz))
            .attr("y", d => yScale(d.intensity) - 10)
            .attr("text-anchor", "middle")
            .attr("fill", d => {
              if (d.type === 'b') return x.bColor;
              if (d.type === 'y') return x.yColor;
              return x.otherColor;
            })
            .text(d => d.label);
          }

        }

        // Tooltip事件
        const tooltip = d3.select("#tooltip");
        function handleMouseOver(event, d) {
          const ionTypeText = d.ionType === "?" ? "?" :
                             d.ionType === "b" ? "b" :
                             d.ionType === "y" ? "y" : d.ionType;
          const relativeIntensity = ((d.intensity / maxIntensity) * 100).toFixed(2);

          tooltip.html(`
            <div class="tooltip-title">${d.label || "?"}</div>
            <div class="tooltip-row">
              <span class="tooltip-label">m/z:</span>
              <span class="tooltip-value">${d.mz}</span>
            </div>
            <div class="tooltip-row">
              <span class="tooltip-label">intensity:</span>
              <span class="tooltip-value">${d.intensity.toLocaleString()}</span>
            </div>
            <div class="tooltip-row">
              <span class="tooltip-label">relative intensity:</span>
              <span class="tooltip-value">${relativeIntensity}%</span>
            </div>
            <div class="tooltip-row">
              <span class="tooltip-label">ion type:</span>
              <span class="tooltip-value">${ionTypeText}</span>
            </div>
          `).style("opacity", 1);
        }

        function handleMouseMove(event) {
          const rect = el.getBoundingClientRect();
          const x = event.clientX - rect.left + 15;
          const y = event.clientY - rect.top - 15;

          // 限制tooltip在容器内
          const tooltipEl = tooltip.node();
          if (x + tooltipEl.offsetWidth > rect.width) {
            tooltip.style("left", (x - tooltipEl.offsetWidth - 30) + "px");
          } else {
            tooltip.style("left", x + "px");
          }

          if (y < 0) {
            tooltip.style("top", "10px");
          } else if (y + tooltipEl.offsetHeight > rect.height) {
            tooltip.style("top", (y - tooltipEl.offsetHeight - 20) + "px");
          } else {
            tooltip.style("top", y + "px");
          }
        }

        function handleMouseOut() {
          tooltip.style("opacity", 0);
        }

        // 修复缩放问题：使用独立的可视比例尺
        function zoomed(event) {
          const newXScale = event.transform.rescaleX(xScale);
          // 更新坐标轴
          xAxisGroup.call(d3.axisBottom(newXScale));
          // 更新谱峰位置
          mainGroup.selectAll(".spectrum-bar")
            .attr("x1", d => newXScale(d.mz))
            .attr("x2", d => newXScale(d.mz));
          // 更新标签位置
          mainGroup.selectAll(".ion-label")
            .attr("x", d => newXScale(d.mz));
        }

        // 按钮事件
        d3.select("#zoom-in").on("click", () => {
          const currentDomain = xScale.domain();
          const range = currentDomain[1] - currentDomain[0];
          const newDomain = [currentDomain[0] + range * 0.1, currentDomain[1] - range * 0.1];
          xScale.domain(newDomain);
          xAxisGroup.call(d3.axisBottom(xScale));
          drawSpectrum();
        });

        d3.select("#zoom-out").on("click", () => {
          const currentDomain = xScale.domain();
          const range = currentDomain[1] - currentDomain[0];
          const newDomain = [currentDomain[0] - range * 0.1, currentDomain[1] + range * 0.1];
          xScale.domain(newDomain);
          xAxisGroup.call(d3.axisBottom(xScale));
          drawSpectrum();
        });

        d3.select("#reset-zoom").on("click", () => {
          xScale.domain([d3.min(formattedData, d => d.mz) - 20, d3.max(formattedData, d => d.mz) + 20]);
          xAxisGroup.call(d3.axisBottom(xScale));
          // 重置缩放状态
          mainGroup.selectAll("rect").call(zoom.transform, d3.zoomIdentity);
          drawSpectrum();
        });

        // 坐标轴标签
        svg.append("text")
          .attr("transform", `translate(${margin.left + innerWidth/2}, ${margin.top + innerHeight + 40})`)
          .attr("text-anchor", "middle")
          .attr("fill", "#555")
          .text(x.titleX);


          if(x.titleY==""){
            if (x.axisY=="absolute") {
              titleY = "Absolute intensity";
            }else{
              titleY = "Relative intensity(%)";
            }
        }else{
            titleY = x.titleY
          }

        svg.append("text")
          .attr("transform", `rotate(-90)`)
          .attr("y", margin.left - 60)
          .attr("x", -(margin.top + innerHeight/2))
          .attr("text-anchor", "middle")
          .attr("fill", "#555")
          .text(titleY);

        // 图表标题
        svg.append("text")
          .attr("x", margin.left + innerWidth/2)
          .attr("y", margin.top - 10)
          .attr("text-anchor", "middle")
          .attr("fill", "#333")
          .attr("font-size", "16px")
          .attr("font-weight", "bold")
          .text(x.title);

        // 初始绘制
        drawSpectrum();





      },

      resize: function(el, width, height) {


      }
    };
  }
});
